﻿#pragma once
#include <string.h>


namespace lix{

	namespace detail {
		template<int DUMMY>
		class CharTable {
		public:
			static const unsigned char hex_digits[256]; 
		};


		template <int DUMMY>
		const unsigned char CharTable<DUMMY>::hex_digits[256] = 
		{
			// 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 0
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 1
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 2
			0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,    // 3
			255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 4
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 5
			255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 6
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 7
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 8
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 9
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // A
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // B
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // C
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // D
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // E
			255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255   // F
		};


	}



	class Character {
	public:


		static unsigned char getHexDigit( char ch )
		{
			return lix::detail::CharTable<0>::hex_digits[ch];
		}

		//! strcmp
		static int strcmp( const char* p1, const char* p2 ){
			return std::strcmp( p1, p2 );
		}
		//! strcmp (wcscmp という関数名がよくわからなくなるのとテンプレートのため) 
		static int strcmp( const wchar_t* p1, const wchar_t* p2 ){
			return std::wcscmp( p1, p2 );
		}

		//! 文字が Ascii コードで見て小文字か返す。
		template<typename CHAR_TYPE>
		inline static bool isLowerCase(CHAR_TYPE ch ){
			return (ch >= 'a' && ch <='z');
		}

		//! 文字が Ascii コードで見て大文字か返す。
		template<typename CHAR_TYPE>
		inline static bool isUpperCase(CHAR_TYPE ch ){
			return (ch >= 'A' && ch <='Z');
		}

		//! 文字が Ascii コードで見て数字か返す。
		template<typename CHAR_TYPE>
		inline static bool isNumeric(CHAR_TYPE ch ){
			return (ch >= '0' && ch <='9');
		}

		//! 引数で受けた文字が Ascii コードで見て空白文字か返す。
		//! 
		//! ここでいう空白文字とは、次のいずれかのこと、
		//! @li 空白文字 ' '
		//! @li 水平タブ文字 '\\t'
		//! @li 垂直タブ文字 '\\v'
		//! @li 書式送り文字 '\\f'
		//! @li 改行文字 '\\n'
		//! @li 復帰文字 '\\r' 
		//! 
		//! ロケールやユニコードの空白などは一切加味しない
		template<typename CHAR_TYPE>
		inline static bool isWhiteSpace( CHAR_TYPE ch ){
			// もっと速い実装はいくらでもあろうが、
			// これで十分高速に最適化してくれるものとコンパイラを信じている。
			// これでも将来的にロケールに悩まされたりするよりは良いのではないかと。
			return ( 
				ch == ' ' || 
				ch == '\t'  || 
				ch == '\v'  || 
				ch == '\f'  || 
				ch == '\n'  || 
				ch == '\r' );
		}

		//! 文字が Ascii コードで見てアルファベットか数字であるとき true を返す。
		template<typename CHAR_TYPE>
		inline static bool isAlphaNumeric( CHAR_TYPE ch ){

			// これはちょっと遅い。
			// 『ちょっとでも高速化』とか考えるなら、256 バイトのテーブルを作って、
			// 各ビットを属性にみたてて（８種類いける）インデックスアクセスとマスクだけにできるが、
			// そこまでセコく高速化しなきゃいけない側面でもないだろう、と。

			return (isLowerCase(ch) || isUpperCase(ch) || isNumeric(ch));
		}



		//! ロケールを無視した大文字変換
		//! C 標準の toupper は無駄にロケールを加味するので。
		template<typename CHAR_TYPE>
		static inline CHAR_TYPE toUpperCase( CHAR_TYPE ch ){
			return isLowerCase(ch) ? ch - ('a'-'A') : ch;	
		}

		//! ロケールを無視した小文字変換
		//! C 標準の toupper は無駄にロケールを加味するので。
		template<typename CHAR_TYPE>
		static inline CHAR_TYPE toLowerCase( CHAR_TYPE ch ){
			return isUpperCase(ch) ? ch + ('a'-'A') : ch;	
		}

	};


}